// 可能与视频不一样，按照视频可能会报错

import loginHeaderVue from "@/views/login/components/login-header.vue"
import { getNewCartGoods } from '@/api/cart'
import { mergeCart } from '@/api/cart'
import { findCart } from '@/api/cart'
import { insertCart } from '@/api/cart'
import { deleteCart } from '@/api/cart'
import { updateCart } from '@/api/cart'
import { checkAllCart } from '@/api/cart'




// 购物车模块
export default {
    // 命名空间
    namespaced: true,
    state: () => {
        return {
            // 购物车信息
            list: []
        }
    },
    getters: {
        // 有效商品列表
        validList(state) {
            // 有效商品： 库存量大于0  (stock)  商品有效标识为 true  (isEffective)
            return state.list.filter(goods => goods.stock > 0 && goods.isEffective)
        },
        // 有效商品总件数
        validTotal(state, getters) {
            return getters.validList.reduce((p, c) => p + c.count, 0)
        },
        // 有效商品总金额
        validAmount(state, getters) {
            // 1.1 * 3 =3.30000000000
            // *100后/100是为了去除浮点数
            // 方法1
            // return getters.validList.reduce((p, c) => p + c.nowPrice * 100 * c.count, 0) / 100
            // 方法2
            return getters.validList.reduce((p, c) => p + parseInt(c.nowPrice * 100) * c.count, 0) / 100

        },

        // 购物车地址内的
        // 无效商品列表
        invalidList(state) {
            // 库存<=0   无效的商品!isEffective
            return state.list.filter(goods => goods.stock <= 0 && !goods.isEffective)
        },
        // 选中商品列表
        selectedList(state, getters) {
            // 从有效商品列表筛选，选中的
            return getters.validList.filter(item => item.selected)
        },
        // 选中商品件数
        selectedTotal(state, getters) {
            return getters.selectedList.reduce((p, c) => p + c.count, 0)
        },
        // 选中商品总金额
        selectedAmount(state, getters) {
            return getters.selectedList.reduce((p, c) => p + (c.nowPrice * 100 * c.count), 0) / 100
        },
        // 是否全选
        isCheckAll(state, getters) {
            // 有效商品数=选中商品数，选中商品不为0
            return getters.validList.length === getters.selectedList.length && getters.selectedList.length !== 0
        }
    },
    // 本地：id skuId name picture price nowPrice count attrsText selected stock isEffective
    // 线上：比上面多 isCollect 有用 discount 无用 两项项信息
    mutations: {


        // 加入购物车
        insertCart(state, payload) {
            // 约定加入购物车字段必须和后端保持一致 payload对象 的字段
            // 插入数据规则:
            // 1.先找下是否有相同商品
            // 2.如果有相同的商品，查询它的数量，累加到payload上，再保存最新位置，原来商品需要删除
            // 3.如果没有相同的商品,保存早最新位置即可
            const sameIndex = state.list.findIndex(goods => goods.skuId === payload.skuId)
                // 逻辑：有相同的给payload累加数量，删除相同skuId的商品
            if (sameIndex > -1) {
                const count = state.list[sameIndex].count
                payload.count += count
                    // 删除原来
                state.list.splice(sameIndex, 1)
            }
            // 追加新的
            state.list.unshift(payload)
        },

        // 修改购物车商品
        updateCart(state, goods) {
            // goods中字段有可能不完整，goods有的信息才去修改。
            // goods 商品对象的字段不固定，对象中有哪些字段就改哪些，字段合理才改
            // 1. goods中必需又skuId，才能找到对应的商品信息
            // console.log(state);
            const updateGoods = state.list.find(item => item.skuId === goods.skuId)
            for (const key in goods) {
                // 布尔类型 false 值需要使用
                if (goods[key] !== null && goods[key] !== undefined && goods[key] !== '') {
                    updateGoods[key] = goods[key]
                }
            }
        },

        // 删除购物车商品
        deleteCart(state, skuId) {
            const index = state.list.findIndex(item => item.skuId === skuId)
            state.list.splice(index, 1)
        },

        // 设置购物车列表
        setCartList(state, payload) {
            // payload为空数组，清空，payload为有值，设置
            state.list = payload
        },

    },
    actions: {
        // 合并本地购物车（登录后才合并,不用区分登录前后）
        //加上async后 mergeLocalCart 就是给Promise对象
        async mergeLocalCart(ctx) {
            // 存储token后调用合并API接口函数进行购物合并
            // 方法1：
            // const cartList = ctx.getters.validList.map(({ skuId, selected, count }) => {
            //     return { skuId, selected, count }
            // })
            // 方法2：
            const cartList = ctx.state.list.map(goods => {
                return {
                    skuId: goods.skuId,
                    selected: goods.selected,
                    count: goods.count
                }
            });
            // 这个mergeCart是api里面的
            await mergeCart(cartList);
            // 合并成功将本地购物车删除（清空本地购物车）
            ctx.commit('setCartList', [])
        },

        // 修改sku规格函数
        updateCartSku(ctx, { oldSkuId, newSku }) {
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 登录 TODO
                    // 这里需要后端提供接口
                    // 1. 获取旧的商品信息
                    // 2. 删除旧的商品
                    // 3. 获取新的skuId + 旧的商品数量 做一个加入购物车操作
                    // 4. 更新列表
                    // 这里的deleteCart，insertCart，findCart是api的
                    const oldGoods = ctx.state.list.find(item => item.skuId === oldSkuId)
                    deleteCart([oldGoods.skuId]).then(() => {
                        return insertCart({ skuId: newSku.skuId, count: oldGoods.count })
                    }).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 本地
                    // 但你修改了sku的时候其实skuId需要更改，相当于把原来的信息移出，创建一条新的商品信息。
                    // 1. 获取旧的商品信息
                    const oldGoods = ctx.state.list.find(item => item.skuId === oldSkuId);
                    // 2. 删除旧的商品
                    ctx.commit('deleteCart', oldSkuId);
                    // 3. 根据新的sku信息和旧的商品信息,合并一条新的商品信息
                    const { skuId, price: nowPrice, inventory: stock, specsText: attrsText } = newSku
                    const newGoods = {...oldGoods, skuId, nowPrice, stock, attrsText };
                    // 4. 去插入即可（添加新的商品）
                    // 不用担心修改后和修改前的规格一样，insertCart已经做了处理
                    ctx.commit('insertCart', newGoods)
                }
            })
        },

        // 批量删除选中商品，也支持清空无效商品
        // 区分:有传参的是清空无效商品
        batchDeleteCart(ctx, isClear) {
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 登录 TODO
                    // 得到需要删除的商品列表（失效，选中）的skuId集合
                    // 这里deleteCart，findCart都是api里的
                    const ids = ctx.getters[isClear ? 'invalidList' : 'selectedList'].map(item => item.skuId)
                    deleteCart(ids).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 本地
                    // 1. 获取选中商品列表，进行遍历调用deleteCart mutataions函数
                    // isClear为true 删除失效商品列表， 否则是删除选中的商品列表
                    ctx.getters[isClear ? 'invalidList' : 'selectedList'].forEach(item => {
                        ctx.commit('deleteCart', item.skuId)
                    })
                    resolve()
                }
            })
        },

        // 做有效商品的全选&反选
        checkAllCart(ctx, selected) {
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 登录 TODO
                    // 这里的checkAllCart和findCart都是api
                    const ids = ctx.getters.validList.map(item => item.skuId)
                    checkAllCart({ selected, ids }).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 本地
                    // 1. 获取有效的商品列表，遍历的去调用修改mutations即可
                    ctx.getters.validList.forEach(goods => {
                        ctx.commit('updateCart', { skuId: goods.skuId, selected })
                    })
                    resolve()
                }
            })
        },

        // 加入购物车
        insertCart(ctx, payload) {
            return new Promise((resolve, reject) => {
                // console.log(ctx.rootState.user);
                if (ctx.rootState.user.profile.token) {
                    // 已登录 TODO
                    // 这里的insertCart和findCart是api里的
                    insertCart({ skuId: payload.skuId, count: payload.count }).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 未登录
                    ctx.commit('insertCart', payload);
                    // 返回的是Promise必须要调用resolve()，否则将来通过then拿不到结果
                    resolve()
                }
            })
        },

        // 获取购物车列表
        findCartList(ctx) {
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 已登录 TODO
                    // findCart是api里的
                    findCart().then(data => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 未登录
                    // 本地
                    // 同时发送请求（ 几个商品发几个请求），等所有请求成功，一并修改本地数据

                    // Promise.all() 可以并列发送多个请求，等所有请求成功，调用then
                    // 所有Promise数组请求成功都会汇总早dataList
                    // Promise.all(Promise数组).then(dataList=>{}) 同时发请求，所有请求成功，得到所有成功结果

                    // 创建Promise对象的方法还有Promise.resolve()  Promise.reject()  new Promise()

                    // Promise.race() 可以并列发送多个请求，等最快的请求成功，调用then
                    // Promise.race(Promise数组).then(data=>{}) 同时发请求，最快的请求成功，得到成功结果

                    // 传参事promise数组
                    const promiseArr = ctx.state.list.map(item => {
                            // 返回接口函数的调用
                            return getNewCartGoods(item.skuId)
                        })
                        // dataList成功结果的集合， 数据顺序和promiseArr顺序一致， 他又是state.list而来的
                    Promise.all(promiseArr).then(dataList => {
                        // console.log(dataList);
                        // 更新本地购物车
                        dataList.forEach((data, i) => {
                            ctx.commit('updateCart', { skuId: ctx.state.list[i].skuId, ...data.result })
                        });
                        // 调用resolve代表操作成功
                        resolve()
                    }).catch(e => {
                        reject(e)
                    })
                }
            })
        },

        // 修改购物车商品(选中状态,数量)
        updateCart(ctx, payload) {
            // payload 中：必须有skuId，其他想修改的属性 selected  count
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 登录 TODO
                    // 已经登录修改服务器
                    // 这里的updateCart，findCart是api里的
                    updateCart(payload).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 未登录修改本地
                    ctx.commit('updateCart', payload)
                    resolve()
                }
            })
        },

        // 删除购物车商品
        deleteCart(ctx, payload) {
            return new Promise((resolve, reject) => {
                if (ctx.rootState.user.profile.token) {
                    // 登录 TODO
                    // 这里deleteCart，findCart都是api里的
                    deleteCart([payload]).then(() => {
                        return findCart()
                    }).then((data) => {
                        ctx.commit('setCartList', data.result)
                        resolve()
                    })
                } else {
                    // 未登录
                    // 本地
                    // 单条删除 payload 就是 skuId
                    ctx.commit('deleteCart', payload)
                    resolve()
                }
            })
        },
    }
}